/**
 * Module resolver for puppeteer scripts.
 * This helps locate modules both in development and packaged environments.
 */

const path = require('path');
const fs = require('fs');

/**
 * Sets up additional module paths to help resolve modules
 * in both development and packaged environments.
 */
function setupModulePaths() {
  const isPackaged = process.env.IS_PACKAGED === 'true';

  console.log('[Module Resolver] Running in', isPackaged ? 'packaged' : 'development', 'mode');
  console.log('[Module Resolver] Current directory:', process.cwd());
  console.log('[Module Resolver] __dirname:', __dirname);

  // Get app resource path from environment (set by main process)
  const resourcesPath = process.env.APP_RESOURCE_PATH || (process.resourcesPath ? process.resourcesPath : '');
  if (resourcesPath) {
    console.log('[Module Resolver] Resources path:', resourcesPath);
  }

  // Determine all possible module paths
  let possibleModulePaths = [];

  if (isPackaged) {
    // In packaged mode, we need to look in various locations
    possibleModulePaths = [
      // Main node_modules in resources
      path.join(resourcesPath, 'node_modules'),
      // Path relative to current script
      path.join(__dirname, 'node_modules'),
      // One level up from current directory
      path.join(__dirname, '..', 'node_modules'),
      // Main app resources node_modules
      path.join(resourcesPath, '..', 'node_modules'),
      // Resources root
      resourcesPath,
      // Parent of script directory
      path.resolve(__dirname, '..'),
      // App directory node_modules
      path.join(process.cwd(), 'node_modules')
    ];
  } else {
    // In development mode
    possibleModulePaths = [
      // Project root node_modules
      path.resolve(__dirname, '..', '..', 'node_modules'),
      // Direct node_modules in puppeteer_ads
      path.join(__dirname, 'node_modules'),
      // App directory node_modules
      path.join(process.cwd(), 'node_modules')
    ];
  }

  // Filter out non-existent paths
  const existingPaths = possibleModulePaths.filter(dirPath => {
    try {
      return fs.existsSync(dirPath);
    } catch (e) {
      return false;
    }
  });

  console.log('[Module Resolver] Found module paths:');
  existingPaths.forEach((p, i) => console.log(`  ${i+1}. ${p}`));

  // Set NODE_PATH environment variable
  const separator = process.platform === 'win32' ? ';' : ':';
  process.env.NODE_PATH = existingPaths.join(separator);

  // Force Node.js to reload its module paths
  try {
    require('module').Module._initPaths();
    console.log('[Module Resolver] Initialized Node module paths');
  } catch (err) {
    console.error('[Module Resolver] Failed to initialize module paths:', err);
  }

  // Check if specific modules can be located
  console.log('[Module Resolver] Testing module resolution:');
  const testModules = ['puppeteer-core', 'puppeteer-extra', 'p-limit', 'mqtt', 'yocto-queue'];

  testModules.forEach(moduleName => {
    try {
      // Try to resolve the module
      const modulePath = require.resolve(moduleName);
      console.log(`  ✅ ${moduleName}: ${modulePath}`);

      // Also check if this is a direct module or a directory
      try {
        const modulePackage = require(`${moduleName}/package.json`);
        console.log(`     Version: ${modulePackage.version}`);
      } catch (err) {
        // Not a package with package.json, might be a direct module
      }
    } catch (err) {
      console.error(`  ❌ ${moduleName}: ${err.message}`);

      // Try to manually locate the module using the node_modules paths
      let found = false;
      for (const basePath of existingPaths) {
        const possibleModulePath = path.join(basePath, moduleName);
        if (fs.existsSync(possibleModulePath)) {
          console.log(`     Found at: ${possibleModulePath}`);
          found = true;
          break;
        }

        // Also check with package.json
        const possiblePackageJson = path.join(basePath, moduleName, 'package.json');
        if (fs.existsSync(possiblePackageJson)) {
          console.log(`     Found package.json at: ${possiblePackageJson}`);
          found = true;
          break;
        }
      }

      if (!found) {
        console.error(`     Not found in any node_modules path!`);
      }
    }
  });

  // Add all node_modules paths to the require paths
  // This is a more direct way to augment the require lookup paths
  const Module = require('module');
  const originalResolveFilename = Module._resolveFilename;

  Module._resolveFilename = function(request, parent, isMain, options) {
    try {
      return originalResolveFilename(request, parent, isMain, options);
    } catch (err) {
      // If module not found, try our additional paths
      if (err.code === 'MODULE_NOT_FOUND') {
        for (const modulePath of existingPaths) {
          try {
            const fullPath = path.join(modulePath, request);
            if (fs.existsSync(fullPath)) {
              return fullPath;
            }

            // Try with package.json/index.js, etc.
            const indexFile = path.join(fullPath, 'index.js');
            const packageJson = path.join(fullPath, 'package.json');

            if (fs.existsSync(indexFile)) {
              return indexFile;
            }

            if (fs.existsSync(packageJson)) {
              const pkg = require(packageJson);
              if (pkg.main) {
                const mainFile = path.join(fullPath, pkg.main);
                if (fs.existsSync(mainFile)) {
                  return mainFile;
                }
              }
            }
          } catch (innerErr) {
            // Continue to next path
          }
        }
      }

      // If we got here, we couldn't resolve it in our paths either
      throw err;
    }
  };

  console.log('[Module Resolver] Setup complete');
}

module.exports = { setupModulePaths };

// If this file is run directly, execute the setup
if (require.main === module) {
  setupModulePaths();
}